跳到主要内容

查找算法 插值查找

什么是插值查找?

插值查找是二分查找的改进版。它是根据要查找的关键字 key 与查找表中的最大最小记录的关键字比较后的查找方法,

在介绍插值查找之前,首先回顾一下二分查找,为什么它一定要是折半,而不是折四分之一或者折更多呢?

打个比方,在英文字典里面查 “apple”,你下意识翻开字典是翻前面的书页还是后面的书页呢?如果再让你查 “zoo”,你又怎么查?很显然,这里你绝对不会是从中间开始查起,而是有一定目的的往前或往后翻。

同样的,比如要在取值范围 1 ~ 10000 之间 100 个元素从小到大 均匀分布 的数组中查找 5, 我们自然会考虑从数组下标较小的开始查找。

经过以上分析,折半查找这种查找方式,不是自适应的(也就是说是傻瓜式的)。二分查找中查找点计算如下:

mid=low+1/2(highlow)mid = low + 1/2 * (high - low)

通过类比,我们可以将查找的点改进为如下(这里就不推导公式了,直接记就行了):

mid=low+(keya[low])/(a[high]a[low])(highlow)mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low)

也就是将上述的比例参数 1/2 改进为自适应的,根据关键字在整个有序表中所处的位置,让 mid 值的变化更靠近关键字 key,这样也就间接地减少了比较次数。

注:对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。

插值查找代码实现

public class InsertSearch {
public static void main(String[] args) {
int[] array = new int[]{-7, -4, -2, 5, 8, 10};
System.out.println("原始数据:" + Arrays.toString(array));
int index = insertSearch(array, 8);
System.out.println("【插入查找】结果下标位置:" + index);
}


/**
* 插入查找
*/
public static int insertSearch(int[] array, int value) {
int mid;
int start = 0;
int end = array.length - 1;

while (start <= end) {
mid = start + (value - array[start]) / (array[end] - array[start]) * (end - start);

// 说明在左边
if (value < array[mid]) {
end = mid - 1;
}
// 说明在右边
else if (value > array[mid]) {
start = mid + 1;
} else {
return mid;
}
}

return -1;
}
}